package com.zhss.eshop.order.service.Impl;

import com.zhss.eshop.common.util.DateProvider;
import com.zhss.eshop.common.util.ObjectUtils;
import com.zhss.eshop.inventory.service.InventoryService;
import com.zhss.eshop.order.constant.OrderStatus;
import com.zhss.eshop.order.constant.PublishedComment;
import com.zhss.eshop.order.domain.dto.OrderInfoDTO;
import com.zhss.eshop.order.domain.dto.OrderItemDTO;
import com.zhss.eshop.order.domain.model.OrderInfo;
import com.zhss.eshop.order.domain.model.OrderItem;
import com.zhss.eshop.order.mapper.OrderInfoMapper;
import com.zhss.eshop.order.mapper.OrderItemMapper;
import com.zhss.eshop.order.price.*;
import com.zhss.eshop.order.price.coupon.CouponCalculator;
import com.zhss.eshop.order.price.freight.FreightCalculator;
import com.zhss.eshop.order.price.promotion.PromotionActivityCalculator;
import com.zhss.eshop.order.price.promotion.PromotionActivityResult;
import com.zhss.eshop.order.price.total.TotalPriceCalculator;
import com.zhss.eshop.order.service.OrderInfoService;
import com.zhss.eshop.order.state.OrderStateManager;
import com.zhss.eshop.promotion.constant.PromotionActivityType;
import com.zhss.eshop.promotion.domain.dto.PromotionActivityDTO;
import com.zhss.eshop.promotion.domain.dto.PromotionCouponDTO;
import com.zhss.eshop.promotion.service.PromotionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class OrderInfoServiceImpl implements OrderInfoService{

    @Resource
    private OrderInfoMapper orderInfoMapper;

    @Resource
    private OrderItemMapper orderItemMapper;
    /**
     * 日期辅助组件
     */
    @Autowired
    private DateProvider dateProvider;
    /**
     * 促销中心接口
     */
    @Autowired
    private PromotionService promotionService;
    /**
     * 默认的订单价格计算组件工厂
     */
    @Autowired
    private DefaultOrderPriceCalculatorFactory defaultOrderPriceCalculatorFactory;
    /**
     * 折扣减免型的订单价格计算组件工厂
     */
    @Autowired
    private DiscountOrderPriceCalculatorFactory discountOrderPriceCalculatorFactory;
    /**
     * 赠品型的订单价格计算组件工厂
     */
    @Autowired
    private GiftOrderPriceCalculatorFactory giftOrderPriceCalculatorFactory;
    /**
     * 优惠券计算组件工厂
     */
    @Autowired
    private CouponCalculatorFactory couponCalculatorFactory;

    /**
     * 订单状态管理器
     */
    @Autowired
    private OrderStateManager orderStateManager;
    /**
     * 库存中心接口
     */
    @Autowired
    private InventoryService inventoryService;

    @Override
    public int deleteByPrimaryKey(Long id) {
        return orderInfoMapper.deleteByPrimaryKey(id);
    }

    @Override
    public OrderInfoDTO insertSelective(OrderInfoDTO order) throws Exception {
        saveOrder(order);
//        orderStateManager.create(order);
//        inventoryService.informSubmitOrderEvent(order);
        promotionService.useCoupon(order.getCouponId(), order.getUserAccountId());

        return order;
    }
    /**
     * 新增订单
     * @param order 订单
     * @return 订单
     * @throws Exception
     */
    private OrderInfoDTO saveOrder(OrderInfoDTO order) throws Exception {
        order.setOrderNo(UUID.randomUUID().toString().replace("-", ""));
        order.setIsPublishedComment(PublishedComment.NO);
        order.setOrderStatus(OrderStatus.UNKNOWN);
        order.setGmtCreate(dateProvider.getCurrentTime());
        order.setGmtModified(dateProvider.getCurrentTime());

        Long orderInfoId = (long) orderInfoMapper.insertSelective(order.clone(OrderInfo.class));
        order.setId(orderInfoId);

        for(OrderItemDTO orderItem : order.getOrderItems()) {
            orderItem.setOrderInfoId(orderInfoId);
            orderItem.setGmtCreate(dateProvider.getCurrentTime());
            orderItem.setGmtModified(dateProvider.getCurrentTime());

            Long orderItemId = (long) orderItemMapper.insertSelective(orderItem.clone(OrderItem.class));

            orderItem.setId(orderItemId);
        }

        return order;
    }

    @Override
    public OrderInfo selectByPrimaryKey(Long id) {
        return orderInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(OrderInfo record) {
        return orderInfoMapper.updateByPrimaryKeySelective(record);
    }

    /**
     * 根据id查询订单
     * @param id 订单id
     * @return 订单
     * @throws Exception
     */
    @Override
    public OrderInfoDTO getById(Long id) throws Exception {
        OrderInfo order = orderInfoMapper.selectByPrimaryKey(id);
        OrderInfoDTO orderInfoDTO=order.clone(OrderInfoDTO.class);
//        setOrderItems(order);
//        setOrderOperateLogs(order);
        return orderInfoDTO;
    }
    /**
     * 为订单查询并且设置订单条目
     * @param order 订单
     * @return 订单
     * @throws Exception
     */
    private OrderInfoDTO setOrderItems(OrderInfoDTO order) throws Exception {
        List<OrderItemDTO> orderItems = ObjectUtils.convertList(
                orderItemMapper.listByOrderInfoId(order.getId()),
                OrderItemDTO.class);
        order.setOrderItems(orderItems);
        return order;
    }

    /**
     * 计算订单价格
     * @param order 订单
     */
    @Override
    public OrderInfoDTO calculateOrderPrice(OrderInfoDTO order) throws Exception {
        // 定义订单的各种价格
        Double totalAmount = 0.0;
        Double discountAmount = 0.0;
        Double freight = 0.0;

        List<OrderItemDTO> giftOrderItems = new ArrayList<OrderItemDTO>();

        for(OrderItemDTO item : order.getOrderItems()) {
            // 查询订单条目使用的促销活动
            PromotionActivityDTO promotionActivity = promotionService.getById(
                    item.getPromotionActivityId());

            // 根据促销活动获取到订单计算组件的工厂
            OrderPriceCalculatorFactory orderPriceCalculatorFactory =
                    getOrderPriceCalculatorFactory(promotionActivity);

            // 从订单计算组件工厂中获取一套订单的价格计算组件
            TotalPriceCalculator totalPriceCalculator = orderPriceCalculatorFactory
                    .createTotalPriceCalculator();
            PromotionActivityCalculator promotionActivityCalculator = orderPriceCalculatorFactory
                    .createPromotionActivityCalculator(promotionActivity);
            FreightCalculator freightCalculator = orderPriceCalculatorFactory
                    .createFreightCalculator();

            // 计算订单条目的总金额
            totalAmount += totalPriceCalculator.calculate(item);

            // 处理促销活动，计算促销活动的减免金额，以及促销活动的赠品
            PromotionActivityResult result = promotionActivityCalculator.calculate(
                    item, promotionActivity);
            discountAmount += result.getDiscountAmount();
            giftOrderItems.addAll(result.getOrderItems());

            // 计算订单条目的运费
            freight += freightCalculator.calculate(order, item, result);
        }

        // 给订单设置计算后的结果（同时已经包含了所有的赠品）
        order.setTotalAmount(totalAmount);
        order.setDiscountAmount(discountAmount);
        order.setFreight(freight);
        order.setPayableAmount(totalAmount + freight - discountAmount);
        order.getOrderItems().addAll(giftOrderItems);

        return order;
    }
    /**
     * 获取一个订单价格计算工厂
     * @param promotionActivity 促销活动类型
     * @return 订单价格计算工厂
     */
    private OrderPriceCalculatorFactory getOrderPriceCalculatorFactory(
            PromotionActivityDTO promotionActivity) {
        if(promotionActivity == null) {
            return defaultOrderPriceCalculatorFactory;
        }

        Integer promotionActivityType = promotionActivity.getType();

        if(PromotionActivityType.DIRECT_DISCOUNT.equals(promotionActivityType)
                || PromotionActivityType.MULTI_DISCOUNT.equals(promotionActivityType)
                || PromotionActivityType.REACH_DISCOUNT.equals(promotionActivityType)) {
            return discountOrderPriceCalculatorFactory;
        } else {
            return giftOrderPriceCalculatorFactory;
        }
    }

    /**
     * 计算优惠券抵扣的金额`
     * @param order
     * @param coupon
     * @return
     */
    @Override
    public OrderInfoDTO calculateCouponDiscountPrice(
            OrderInfoDTO order, PromotionCouponDTO coupon) throws Exception {
        CouponCalculator couponCalculator = couponCalculatorFactory.create(coupon);
        Double couponAmount = couponCalculator.calculate(order, coupon);
        order.setCouponAmount(couponAmount);
        order.setPayableAmount(order.getPayableAmount() - couponAmount);
        return order;
    }

    /**
     * 取消订单^
     * @param id 订单id
     * @return 处理结果
     * @throws Exception
     */
    @Override
    public Boolean cancel(Long id) throws Exception {
        OrderInfoDTO order = getById(id);
        if(order == null ) {
            return false;
        }

        if(!orderStateManager.canCancel(order)) {
            return false;
        }

        orderStateManager.cancel(order);
        inventoryService.informCancelOrderEvent(order);

        return true;
    }

}
